const { cos, cosConfig } = require('../config/cos.config');
const db = require('../models');
const FileMetadata = db.FileMetadata;

// 尝试导入sharp，如果失败则使用备用方法
let sharp;
try {
  sharp = require('sharp');
  console.log('已成功加载sharp图像处理库');
} catch (err) {
  console.warn('无法加载sharp图像处理库，将使用备用方法:', err.message);
}

// 生成资源的永久URL
const getPublicUrl = (key) => {
  // 腾讯云COS的公开URL格式
  return `https://${cosConfig.Bucket}.cos.${cosConfig.Region}.myqcloud.com/${encodeURIComponent(key)}`;
};

// 为图片生成缩略图并保存到COS
const generateAndSaveThumbnail = async (imageKey) => {
  console.log('正在为图片生成缩略图:', imageKey);
  
  try {
    // 如果sharp库不可用，则直接使用原图作为缩略图
    if (!sharp) {
      console.warn('由于sharp库不可用，将使用原图作为缩略图');
      
      // 从原始imageKey中提取文件夹路径
      const keyParts = imageKey.split('/');
      const fileName = keyParts[keyParts.length - 1];
      
      // 确定文件夹路径（去掉文件名）
      let folderPath = '';
      if (keyParts.length > 1) {
        folderPath = keyParts.slice(0, -1).join('/');
      }
      
      // 创建缩略图路径: 原文件夹/thumbnail/文件名.png
      const fileNameWithoutExt = fileName.substring(0, fileName.lastIndexOf('.')) || fileName;
      const thumbnailKey = folderPath 
        ? `${folderPath}/thumbnail/${fileNameWithoutExt}.png`
        : `thumbnail/${fileNameWithoutExt}.png`;
      
      // 获取原始图片
      const imageResult = await cos.getObject({
        Bucket: cosConfig.Bucket,
        Region: cosConfig.Region,
        Key: imageKey
      });
      
      if (!imageResult.Body) {
        throw new Error('获取图片内容失败');
      }
      
      // 直接使用原图上传为缩略图
      await cos.putObject({
        Bucket: cosConfig.Bucket,
        Region: cosConfig.Region,
        Key: thumbnailKey,
        Body: imageResult.Body,
        ContentType: imageResult.headers['content-type'] || 'image/jpeg',
        ACL: 'public-read'
      });
      
      console.log('使用原图作为缩略图上传成功:', thumbnailKey);
      
      // 更新或创建文件元数据
      const [metadata, created] = await FileMetadata.findOrCreate({
        where: { cosKey: imageKey },
        defaults: {
          thumbnailUrl: thumbnailKey,
          type: 'image'
        }
      });
      
      // 如果记录已存在但没有缩略图，则更新
      if (!created && !metadata.thumbnailUrl) {
        await metadata.update({ thumbnailUrl: thumbnailKey });
      }
      
      return thumbnailKey;
    }
    
    // 使用sharp库处理图片（如果可用）
    // 获取原始图片内容
    const imageResult = await cos.getObject({
      Bucket: cosConfig.Bucket,
      Region: cosConfig.Region,
      Key: imageKey
    });
    
    if (!imageResult.Body) {
      throw new Error('获取图片内容失败');
    }
    
    // 从原始imageKey中提取文件夹路径
    const keyParts = imageKey.split('/');
    const fileName = keyParts[keyParts.length - 1];
    
    // 确定文件夹路径（去掉文件名）
    let folderPath = '';
    if (keyParts.length > 1) {
      folderPath = keyParts.slice(0, -1).join('/');
    }
    
    // 创建缩略图路径: 原文件夹/thumbnail/文件名.png
    const fileNameWithoutExt = fileName.substring(0, fileName.lastIndexOf('.')) || fileName;
    const thumbnailKey = folderPath 
      ? `${folderPath}/thumbnail/${fileNameWithoutExt}.png`
      : `thumbnail/${fileNameWithoutExt}.png`;
    
    // 使用sharp处理图片，生成缩略图
    const thumbnailBuffer = await sharp(imageResult.Body)
      .resize(200, 150, { fit: 'inside', withoutEnlargement: true })
      .toFormat('png')
      .toBuffer();
    
    // 上传缩略图到COS
    await cos.putObject({
      Bucket: cosConfig.Bucket,
      Region: cosConfig.Region,
      Key: thumbnailKey,
      Body: thumbnailBuffer,
      ContentType: 'image/png',
      ACL: 'public-read'
    });
    
    console.log('缩略图生成并上传成功:', thumbnailKey);
    
    // 更新或创建文件元数据
    const [metadata, created] = await FileMetadata.findOrCreate({
      where: { cosKey: imageKey },
      defaults: {
        thumbnailUrl: thumbnailKey,
        type: 'image'
      }
    });
    
    // 如果记录已存在但没有缩略图，则更新
    if (!created && !metadata.thumbnailUrl) {
      await metadata.update({ thumbnailUrl: thumbnailKey });
    }
    
    return thumbnailKey;
  } catch (error) {
    console.error('生成缩略图失败:', error);
    return null;
  }
};

// 获取指定前缀的所有对象
exports.listObjects = async (req, res) => {
  try {
    let { prefix = '' } = req.query;
    console.log('原始请求前缀:', prefix);
    
    // 应用根目录配置
    if (cosConfig.RootDirectory) {
      // 如果设置了根目录并且请求的是根目录，则使用配置的根目录
      if (!prefix) {
        prefix = cosConfig.RootDirectory;
        console.log('使用配置的根目录:', prefix);
      } else {
        // 如果请求的是子目录，需要确保它是根目录的子目录
        // 首先去除根目录的路径前缀
        if (prefix.startsWith(cosConfig.RootDirectory)) {
          console.log('请求的是根目录的子目录，保持原样:', prefix);
        } else {
          // 如果不是根目录的子目录，则拒绝访问
          console.warn('尝试访问根目录外的内容，已拒绝:', prefix);
          return res.status(403).json({
            success: false,
            message: '无权访问此目录'
          });
        }
      }
    }
    
    console.log('最终使用的前缀:', prefix);
    
    // 确保前缀以 / 结尾
    const normalizedPrefix = prefix ? (prefix.endsWith('/') ? prefix : `${prefix}/`) : '';
    
    // 检查是否在thumbnail文件夹内，如果是则不执行生成缩略图逻辑
    const isThumbnailFolder = normalizedPrefix.includes('/thumbnail/') || normalizedPrefix === 'thumbnail/';
    if (isThumbnailFolder) {
      console.log('当前在缩略图文件夹内，将不会生成新的缩略图');
    }
    
    // 获取COS对象
    const result = await cos.getBucket({
      Bucket: cosConfig.Bucket,
      Region: cosConfig.Region,
      Prefix: normalizedPrefix,
      Delimiter: '/'  // 使用分隔符来区分文件夹
    });

    // 处理文件夹（CommonPrefixes）
    const folders = result.CommonPrefixes.map(item => {
      const folderKey = item.Prefix;
      const folderName = folderKey.replace(normalizedPrefix, '').replace('/', '');
      return {
        key: folderKey,
        name: folderName,
        type: 'folder'
      };
    });

    // 处理文件（Contents）
    const files = result.Contents
      .filter(item => item.Key !== normalizedPrefix) // 过滤掉当前文件夹
      .filter(item => {
        // 过滤掉缩略图文件夹内容，但保留当前目录下的其他内容
        const relativePath = item.Key.replace(normalizedPrefix, '');
        return !relativePath.startsWith('thumbnail/') && !relativePath.includes('/thumbnail/');
      })
      .map(item => {
        const fileName = item.Key.replace(normalizedPrefix, '');
        const isVideo = /\.(mp4|avi|mov|wmv|flv|mkv)$/i.test(fileName);
        const isImage = /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(fileName);
        
        return {
          key: item.Key,
          name: fileName,
          size: item.Size,
          lastModified: item.LastModified,
          type: isVideo ? 'video' : isImage ? 'image' : 'file',
          // 添加永久URL
          url: getPublicUrl(item.Key)
        };
      });

    // 合并结果
    const items = [...folders, ...files];
    
    // 获取元数据信息
    const itemKeys = items.map(item => item.key);
    const metadata = await FileMetadata.findAll({
      where: {
        cosKey: itemKeys
      }
    });
    console.log(`找到 ${metadata.length} 条元数据记录`);
    
    // 将元数据信息合并到结果中
    const metadataMap = metadata.reduce((acc, item) => {
      acc[item.cosKey] = item;
      return acc;
    }, {});
    
    const enrichedItems = items.map(item => {
      const meta = metadataMap[item.key];
      
      let result = {
        ...item,
        nickname: (meta && meta.nickname) || item.name
      };
      
      if (meta) {
        result.id = meta.id;
        
        // 如果有缩略图URL，使用永久URL
        if (meta.thumbnailUrl) {
          try {
            console.log('生成缩略图永久URL:', meta.thumbnailUrl);
            result.thumbnailUrl = getPublicUrl(meta.thumbnailUrl);
            console.log('生成的缩略图URL:', result.thumbnailUrl);
          } catch (error) {
            console.error('获取缩略图URL失败:', error);
          }
        }
      }
      
      // 如果是图片类型且没有缩略图，自动尝试生成 (但在thumbnail文件夹内不执行)
      if (!isThumbnailFolder && item.type === 'image' && !result.thumbnailUrl) {
        // 在响应返回后异步生成缩略图
        setTimeout(async () => {
          try {
            const thumbnailKey = await generateAndSaveThumbnail(item.key);
            console.log(`异步生成缩略图完成: ${thumbnailKey}`);
          } catch (err) {
            console.error('异步生成缩略图失败:', err);
          }
        }, 0);
      }
      
      return result;
    });

    res.json({
      success: true,
      data: enrichedItems,
      currentPrefix: normalizedPrefix,
      isThumbnailFolder, // 额外返回是否在缩略图文件夹的标志
      isRootDirectory: !prefix || prefix === cosConfig.RootDirectory, // 添加是否在根目录的标志
      rootDirectory: cosConfig.RootDirectory // 添加根目录信息
    });
  } catch (error) {
    console.error('获取对象列表失败:', error);
    res.status(500).json({ 
      success: false, 
      message: '获取对象列表失败', 
      error: error.message 
    });
  }
};

// 获取对象URL
exports.getObjectUrl = async (req, res) => {
  try {
    const { key } = req.params;
    
    // 返回永久URL而不是临时签名URL
    const url = getPublicUrl(key);
    
    res.json({
      success: true,
      url
    });
  } catch (error) {
    console.error('获取对象URL失败:', error);
    res.status(500).json({ 
      success: false, 
      message: '获取对象URL失败', 
      error: error.message 
    });
  }
};

// 获取单个图片的缩略图（如果没有则生成）
exports.getImageThumbnail = async (req, res) => {
  try {
    const { key } = req.params;
    console.log('请求获取/生成图片缩略图:', key);
    
    // 查找元数据
    const metadata = await FileMetadata.findOne({
      where: { cosKey: key }
    });
    
    // 如果已有缩略图，直接返回
    if (metadata && metadata.thumbnailUrl) {
      console.log('找到现有缩略图:', metadata.thumbnailUrl);
      return res.json({
        success: true,
        thumbnailUrl: getPublicUrl(metadata.thumbnailUrl)
      });
    }
    
    // 生成缩略图
    console.log('未找到缩略图，正在生成...');
    const thumbnailKey = await generateAndSaveThumbnail(key);
    
    if (thumbnailKey) {
      console.log('缩略图生成成功:', thumbnailKey);
      return res.json({
        success: true,
        thumbnailUrl: getPublicUrl(thumbnailKey)
      });
    }
    
    console.log('缩略图生成失败');
    return res.status(404).json({
      success: false,
      message: '无法生成缩略图'
    });
  } catch (error) {
    console.error('获取图片缩略图失败:', error);
    res.status(500).json({ 
      success: false, 
      message: '获取图片缩略图失败', 
      error: error.message 
    });
  }
};

// 上传文件到指定目录
exports.uploadFile = async (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({
        success: false,
        message: '未提供文件'
      });
    }

    // 获取配置的最大文件大小
    const maxFileSize = parseInt(process.env.MAX_FILE_SIZE || 20000, 10) * 1024 * 1024;
    
    // 检查文件大小是否超过限制
    if (req.file.size > maxFileSize) {
      return res.status(413).json({
        success: false,
        message: `文件大小超过限制，最大允许 ${maxFileSize / (1024 * 1024)}MB`
      });
    }

    const { prefix = '' } = req.body;
    const fileName = req.file.originalname;
    
    console.log('上传文件到目录:', prefix, '文件名:', fileName, '文件大小:', `${(req.file.size / (1024 * 1024)).toFixed(2)}MB`);
    
    // 构建完整的文件路径
    const fileKey = prefix ? 
      (prefix.endsWith('/') ? `${prefix}${fileName}` : `${prefix}/${fileName}`) : 
      fileName;
    
    // 验证上传路径是否在允许的根目录内
    if (cosConfig.RootDirectory && !fileKey.startsWith(cosConfig.RootDirectory)) {
      console.warn('尝试上传到根目录外的位置，已拒绝:', fileKey);
      return res.status(403).json({
        success: false,
        message: '无权在此位置上传文件'
      });
    }
    
    // 上传文件到COS
    const result = await cos.putObject({
      Bucket: cosConfig.Bucket,
      Region: cosConfig.Region,
      Key: fileKey,
      Body: req.file.buffer,
      ContentType: req.file.mimetype,
      ContentLength: req.file.size
    });
    
    console.log('文件上传成功:', fileKey, result);
    
    // 判断文件类型
    const isVideo = /\.(mp4|avi|mov|wmv|flv|mkv)$/i.test(fileName);
    const isImage = /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(fileName);
    const fileType = isVideo ? 'video' : isImage ? 'image' : 'file';
    
    // 为图片文件自动生成缩略图
    if (isImage) {
      console.log('检测到图片文件，将异步生成缩略图');
      setTimeout(async () => {
        try {
          const thumbnailKey = await generateAndSaveThumbnail(fileKey);
          console.log(`异步生成缩略图完成: ${thumbnailKey}`);
        } catch (err) {
          console.error('异步生成缩略图失败:', err);
        }
      }, 0);
    }
    
    // 创建元数据记录
    await FileMetadata.findOrCreate({
      where: { cosKey: fileKey },
      defaults: {
        nickname: fileName,
        type: fileType
      }
    });
    
    res.json({
      success: true,
      message: '文件上传成功',
      data: {
        key: fileKey,
        url: getPublicUrl(fileKey),
        type: fileType
      }
    });
  } catch (error) {
    console.error('上传文件失败:', error);
    res.status(500).json({ 
      success: false, 
      message: '上传文件失败', 
      error: error.message 
    });
  }
};

// 删除文件或文件夹
exports.deleteObjects = async (req, res) => {
  try {
    const { keys } = req.body;
    
    if (!Array.isArray(keys) || keys.length === 0) {
      return res.status(400).json({
        success: false,
        message: '未提供要删除的对象'
      });
    }
    
    console.log('请求删除对象:', keys);
    
    // 验证删除路径是否在允许的根目录内
    if (cosConfig.RootDirectory) {
      for (const key of keys) {
        if (!key.startsWith(cosConfig.RootDirectory)) {
          console.warn('尝试删除根目录外的内容，已拒绝:', key);
          return res.status(403).json({
            success: false,
            message: '无权删除此内容'
          });
        }
      }
    }
    
    const deleteResults = [];
    
    // 逐个处理删除请求
    for (const key of keys) {
      // 判断是文件还是文件夹
      const isFolder = key.endsWith('/');
      
      if (isFolder) {
        // 如果是文件夹，需要递归删除里面的所有内容
        console.log('删除文件夹:', key);
        
        // 1. 列出文件夹内所有对象
        const listResponse = await cos.getBucket({
          Bucket: cosConfig.Bucket,
          Region: cosConfig.Region,
          Prefix: key,
          MaxKeys: 1000
        });
        
        // 2. 获取所有对象的键
        const objectsToDelete = listResponse.Contents.map(item => ({ Key: item.Key }));
        
        if (objectsToDelete.length > 0) {
          // 3. 批量删除对象
          const deleteResponse = await cos.deleteMultipleObject({
            Bucket: cosConfig.Bucket,
            Region: cosConfig.Region,
            Objects: objectsToDelete
          });
          
          console.log(`已删除文件夹 ${key} 中的 ${objectsToDelete.length} 个对象`);
          deleteResults.push({
            key,
            type: 'folder',
            deleted: true,
            childrenCount: objectsToDelete.length
          });
        } else {
          console.log(`文件夹 ${key} 为空，无需删除内容`);
          deleteResults.push({
            key,
            type: 'folder',
            deleted: true,
            childrenCount: 0
          });
        }
      } else {
        // 如果是文件，直接删除
        console.log('删除文件:', key);
        await cos.deleteObject({
          Bucket: cosConfig.Bucket,
          Region: cosConfig.Region,
          Key: key
        });
        
        deleteResults.push({
          key,
          type: 'file',
          deleted: true
        });
      }
      
      // 删除相关的元数据记录
      await FileMetadata.destroy({
        where: { cosKey: key }
      });
      
      // 如果删除的是图片，也尝试删除它的缩略图
      if (/\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(key)) {
        try {
          // 查找图片对应的元数据获取缩略图路径
          const imageMetadata = await FileMetadata.findOne({
            where: { cosKey: key }
          });
          
          if (imageMetadata && imageMetadata.thumbnailUrl) {
            console.log('删除关联的缩略图:', imageMetadata.thumbnailUrl);
            // 删除缩略图文件
            await cos.deleteObject({
              Bucket: cosConfig.Bucket,
              Region: cosConfig.Region,
              Key: imageMetadata.thumbnailUrl
            });
          }
        } catch (thumbnailError) {
          console.error('删除缩略图失败:', thumbnailError);
        }
      }
    }
    
    res.json({
      success: true,
      message: '删除对象成功',
      data: deleteResults
    });
  } catch (error) {
    console.error('删除对象失败:', error);
    res.status(500).json({ 
      success: false, 
      message: '删除对象失败', 
      error: error.message 
    });
  }
};

// 创建文件夹
exports.createFolder = async (req, res) => {
  try {
    const { prefix = '', folderName } = req.body;
    
    if (!folderName) {
      return res.status(400).json({
        success: false,
        message: '文件夹名称不能为空'
      });
    }
    
    // 移除不允许的字符
    const sanitizedFolderName = folderName.replace(/[\\/:*?"<>|]/g, '_');
    
    // 构建完整的文件夹路径（确保以斜杠结尾）
    const folderKey = prefix 
      ? (prefix.endsWith('/') ? `${prefix}${sanitizedFolderName}/` : `${prefix}/${sanitizedFolderName}/`) 
      : `${sanitizedFolderName}/`;
    
    console.log('尝试创建文件夹:', folderKey);
    
    // 验证创建路径是否在允许的根目录内
    if (cosConfig.RootDirectory && !folderKey.startsWith(cosConfig.RootDirectory)) {
      console.warn('尝试在根目录外创建文件夹，已拒绝:', folderKey);
      return res.status(403).json({
        success: false,
        message: '无权在此位置创建文件夹'
      });
    }
    
    // 在腾讯云COS中，创建文件夹实际上是创建一个键以斜杠结尾的空对象
    const result = await cos.putObject({
      Bucket: cosConfig.Bucket,
      Region: cosConfig.Region,
      Key: folderKey,
      Body: '',
      ContentLength: 0
    });
    
    console.log('文件夹创建成功:', folderKey, result);
    
    // 创建文件夹元数据记录
    await FileMetadata.findOrCreate({
      where: { cosKey: folderKey },
      defaults: {
        nickname: sanitizedFolderName,
        type: 'folder'
      }
    });
    
    res.json({
      success: true,
      message: '文件夹创建成功',
      data: {
        key: folderKey,
        name: sanitizedFolderName,
        type: 'folder'
      }
    });
  } catch (error) {
    console.error('创建文件夹失败:', error);
    res.status(500).json({ 
      success: false, 
      message: '创建文件夹失败', 
      error: error.message 
    });
  }
}; 